#include <stdio.h>        /* for printf() and fprintf() */
#include <sys/socket.h>	  /* for socket(), connect(), send(), and recv() */
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>	  /* for sockaddr_in and inet_addr() */
#include <stdlib.h>       /* for exit() */
#include <stdint.h>       /* for uint32_t */
#include <unistd.h>
#include <string.h>       /* for memcpy */

#include "GPSFraming.h"
#include "GPSEncode.h"
#include "structs.h"

#define BUFF_SIZE 128
#define STRING_BUFF 50


void printLocations(void *buffer, int length);
void nl();

int main(int argc, char *argv[])
{
	void *send_array;
	uint8_t recieve_array[BUFF_SIZE];
	char string_buffer[STRING_BUFF];
	size_t size;
	char server[16]="";
	header h;
	int user_id;
	int i;
	char *socket = "25500";
	int exit = 0;
	
//	if(argc >= 2)
//		server = argv[1];
//	if(argc >= 3)
//		socket = argv[2];

	while(server[0] == 0)
	{
		printf("Please enter your server address: ");
		readLine(server, 16, stdin);
		nl();
	}
	
	
while(1)
{
	//TODO recieve input for:
	//server
	//task
	//relevent attributes
	printf("Options:\n1)Change server [%s]\n2)Update Location\n3)Get Friends' Location\n4)Get Friend's History\n5) Leave\n:", server);	
	
	readLine(string_buffer, STRING_BUFF, stdin);
	int choice = atoi(string_buffer);
	
	if(choice > 5 || choice < 1) continue;
	if(choice == 1)
	{
		printf("Please enter your server address: ");
		readLine(server, 16, stdin);
		nl();
		while(server[0] == 0)
		{
			printf("Please enter your server address: ");
			readLine(server, 16, stdin);
			nl();
		}
		continue;
	}
	
	//Convert to packet type enum
	if(choice == 5) choice = LEAVE;
//	if(choice >=2 && choice <=4) choice = (choice-2)*2;
	switch(choice)
	{
		case 2:
			choice = UPDATE;
			break;
		case 3:
			choice = FRIENDS_REQ;
			break;
		case 4:
			choice = HISTORY_REQ;
			break;
		default:
			break;
	}
	
	//set up array to send
	switch(choice)
	{
		case UPDATE: //Update location
			
			printf("Please enter your user ID:");
			readLine(string_buffer, STRING_BUFF, stdin);
			nl();
			
			int u_id = atoi(string_buffer);
			
			printf("Please enter your Latitude:");
			readLine(string_buffer, STRING_BUFF, stdin);
			nl();
			
			float latitude = atof(string_buffer);
			
			printf("Please enter longitude:");
			readLine(string_buffer, STRING_BUFF, stdin);
			nl();
			
			float longitude = atof(string_buffer);
			
			printf("Please enter altitude:");
			readLine(string_buffer, STRING_BUFF, stdin);
			nl();
			
			float altitude = atof(string_buffer);
			
			send_array = malloc(sizeof(header)+sizeof(location));

			location l;

			init_header(&h, UPDATE, 0);
			
			l.latitude = (uint32_t)latitude;
			l.longitude = (uint32_t)longitude;
			l.altitude = (uint32_t)altitude;
			l.u_id = u_id;
			
			encode_header(&h);
			encode_location(&l);

			memcpy(send_array, &h, sizeof(header));
			memcpy(send_array+sizeof(header), &l, sizeof(location));

			size = sizeof(header) + sizeof(location);
			
			break;
		case FRIENDS_REQ:   
			//request Friend's location
			send_array = malloc(BUFF_SIZE);
			void *send_array_pointer=send_array+sizeof(header);
						
			printf("Enter a friend's ID (0 exits):");
			readLine(string_buffer, STRING_BUFF, stdin);
			nl();
			
			for(i = 0; string_buffer[0] != '0'  ; i++)
			{
				((uint32_t*)send_array_pointer)[i] = htonl(atoi(string_buffer));
				printf("Enter a friend's ID (0 exits):");
				readLine(string_buffer, STRING_BUFF, stdin);
				nl();
			}
			
			
			
			init_header(&h,FRIENDS_REQ,i);
			encode_header(&h);

			size = sizeof(header) + sizeof(uint32_t)*i;
			
			memcpy(send_array, &h, sizeof(header));
			
			break;
		case HISTORY_REQ:
			printf("Enter a friend's ID:");
			readLine(string_buffer, STRING_BUFF, stdin);
			nl();
			
			user_id = htonl(atoi(string_buffer));
			
			init_header(&h,HISTORY_REQ,0);
			
			size = sizeof(header)+sizeof(uint32_t);
			send_array = malloc(size);
			encode_header(&h);
			
			memcpy(send_array, &h, sizeof(header) );
			memcpy(send_array+sizeof(header), &user_id, sizeof(uint32_t) );
			
			break;
		case LEAVE:
			init_header(&h, LEAVE, 0);
			send_array = malloc(sizeof(header));
			
			encode_header(&h);
			memcpy(send_array, &h, sizeof(header));
			break;
		default:
			ExitWithMessage("Not a valid option");
			break;
	}
//	printf("Creating socket\n");
	int socket = SetupTCPClientSocket(server,"25412");
	if(socket < 0)
		ExitWithMessage("Could not create socket");
//	printf("Created socket\n");

//	printf("Opening stream\n");
	FILE *stream = fdopen(socket, "r+");
	if(stream == NULL)
		ExitWithMessage("Could not open stream");
//	printf("Opened stream\n");

//	printf("Sending on stream\n");
	if(PutMsg(send_array, size, stream) < 0)
		ExitWithMessage("Failed to send on stream");
	free(send_array);
//	printf("Sent on stream\n");

//	printf("Getting response\n");
	size_t returned = GetNextMsg(stream, recieve_array, BUFF_SIZE);
	if( returned < sizeof(header))
		ExitWithMessage("Recieved partial packet");
//	printf("Got response\n");

	memcpy(&h, recieve_array, sizeof(header));
	decode_header(&h);

	switch(choice)
	{
		case UPDATE:
			if(h.type != UPDATE_ACK)
				ExitWithMessage("Recieved not UPDATE_ACK garbage");
			
			printf("Location Updated\n");
			break;
		case FRIENDS_REQ:
			if(h.type != FRIENDS_RESP)
				ExitWithMessage("Recieved not FRIENDS_RESP garbage");
			
			printf("Found Friends:\n");
			printLocations(recieve_array+sizeof(h) , h.length);
			break;
		case HISTORY_REQ:
			if(h.type != HISTORY_RESP)
				ExitWithMessage("Recieved not HISTORY_RESP garbage");
			
		//	printf("History of %d:\n",  );
			printLocations(recieve_array+sizeof(h) , h.length);
			break;
		case LEAVE:
			exit=1;
			printf("Exiting, Goodbye\n");
			break;
			
		default:
			ExitWithMessage("Not valid option :");
			break;
	}
	close(socket);
	if(exit != 0)
		return 0;
}	
}

void printLocations(void *buffer, int length)
{
	printf("length %d\n", length);
	int i;
	for(i = 0; i<length; i++, buffer+=sizeof(location))
	{
		location l = *(location*)buffer;
		decode_location(&l);
		
		printf("User: %d\n", l.u_id);
		printf("Latitude: %d\nLongitude: %d\nAltitude: %d\n\n", l.latitude, l.longitude, l.altitude);
		getchar();
	}
}

void nl()
{
	printf("\n");
}
